package model

import (
	"gopkg.in/mgo.v2/bson"
	"src/config"
	newtime "src/util/time"
)

type Reply struct {
	ID             bson.ObjectId `bson:"_id,omitempty" json:"id,omitempty"`
	Status         int           `bson:"status" json:"status"`
	ReplyAnonymity bool          `bson:"reply_anonymity" json:"reply_anonymity"`
	Anonymity      bool          `bson:"anonymity" json:"anonymity"`
	UserID         string        `bson:"user_id" json:"user_id"`
	ForumPostId    string        `bson:"forumpost_id" json:"forumpost_id"`
	TopicID        string        `bson:"topic_id" json:"topic_id"`
	ReplyID        string        `bson:"reply_id" json:"reply_id"`
	ReplyUserID    string        `bson:"reply_usber_id" json:"reply_user_id"`
	Level          int           `bson:"level" json:"level"`
	Userinfo       User          `bson:"userinfo" json:"userinfo"`
	IssueTime      int64         `bson:"issue_time" json:"issue_time"`
	Text           string        `bson:"text" json:"text"`
	Imgs           []Img         `bson:"imgs" json:"imgs"`
}

func CreateReply(reply Reply) (Reply, error) {
	reply.IssueTime = newtime.GetMilliTimestamp()
	reply.Status = config.ReplyCommonStatus
	query := bson.M{
		"_id": bson.ObjectIdHex(reply.ReplyID),
	}
	c, err := findComment(query, DefaultSelector)
	if err == nil {
		reply.Level = 2
		reply.ReplyUserID = c.UserID
		reply.ReplyAnonymity = c.Anonymity
	} else {
		r, err := findReply(query, DefaultSelector)
		if err != nil {
			return Reply{}, err
		}
		reply.ReplyUserID = r.UserID
		reply.Level = r.Level + 1
		reply.ReplyAnonymity = r.Anonymity
	}

	err = insertReply(reply)
	if err != nil {
		return Reply{}, err
	}
	return findReply(reply, DefaultSelector)
}
func DeleteReply(id, userid string, admin bool) (Reply, error) {
	if !bson.IsObjectIdHex(id) {
		return Reply{}, config.ErrorIDFormatWrong
	}
	var query bson.M
	if admin {
		query = bson.M{
			"_id": bson.ObjectIdHex(id),
		}
	} else {
		query = bson.M{
			"_id":     bson.ObjectIdHex(id),
			"user_id": userid,
		}
	}
	update := bson.M{
		"$set": bson.M{
			"status": config.ReplyDeleteStatus,
		},
	}
	err := updateReply(query, update)
	if err != nil {
		return Reply{}, err
	}
	return findReply(query, DefaultSelector)
}
func GetReplyByComment(id string, page, per_page int, userid string) ([]Reply, error) {
	if !bson.IsObjectIdHex(id) {
		return []Reply{}, config.ErrorIDFormatWrong
	}
	query := bson.M{
		"topic_id": id,
		"status":   config.ReplyCommonStatus,
	}
	fields := []string{
		"issue_time",
	}
	replies, err := findReplys(query, DefaultSelector, page, per_page, fields...)
	for i := 0; i < len(replies); i++ {
		if replies[i].ReplyAnonymity {
			replies[i].ReplyUserID = ""
		}
		if replies[i].Anonymity && replies[i].UserID != userid {
			replies[i].UserID = ""
		} else {
			replies[i].Userinfo, err = GetUserInfo(replies[i].UserID)
		}
	}
	return replies, err
}
func GetReplyByForumpost(id string, page, per_page int) ([]Reply, error) {
	if !bson.IsObjectIdHex(id) {
		return []Reply{}, config.ErrorIDFormatWrong
	}
	query := bson.M{
		"forumpost_id": id,
		"status":       config.ReplyCommonStatus,
	}
	fields := []string{
		"issue_time",
	}
	replies, err := findReplys(query, DefaultSelector, page, per_page, fields...)
	for i := 0; i < len(replies); i++ {
		if replies[i].ReplyAnonymity {
			replies[i].ReplyUserID = ""
		}
		if replies[i].Anonymity {
			replies[i].UserID = ""
		} else {
			replies[i].Userinfo, err = GetUserInfo(replies[i].UserID)
		}
	}
	return replies, err
}

func GetReplyByCommentALL(id string) ([]Reply, error) {
	if !bson.IsObjectIdHex(id) {
		return []Reply{}, config.ErrorIDFormatWrong
	}
	query := bson.M{
		"topic_id": id,
		"status":   config.ReplyCommonStatus,
	}
	return findReplysALL(query)
}
func GetReplyByReplyALL(id string) ([]Reply, error) {
	if !bson.IsObjectIdHex(id) {
		return []Reply{}, config.ErrorIDFormatWrong
	}
	query := bson.M{
		"reply_id": id,
		"status":   config.ReplyCommonStatus,
	}
	return findReplysALL(query)
}
func GetReplyByPostALL(id string) ([]Reply, error) {
	if !bson.IsObjectIdHex(id) {
		return []Reply{}, config.ErrorIDFormatWrong
	}
	query := bson.M{
		"forumpost_id": id,
		"status":       config.ReplyCommonStatus,
	}
	return findReplysALL(query)
}

func GetReplyByid(id string) (Reply, error) {
	if !bson.IsObjectIdHex(id) {
		return Reply{}, config.ErrorIDFormatWrong
	}
	query := bson.M{
		"_id":    bson.ObjectIdHex(id),
		"status": config.ReplyCommonStatus,
	}
	reply, err := findReply(query, DefaultSelector)
	if err != nil {
		return Reply{}, err
	}
	if reply.ReplyAnonymity {
		reply.ReplyUserID = ""
	}
	if reply.Anonymity {
		reply.UserID = ""
	} else {
		reply.Userinfo, err = GetUserInfo(reply.UserID)
	}
	return reply, err
}

/*******************/
func updateReply(query, update interface{}) error {
	sess := globalSess.Clone()
	defer sess.Close()
	replyTable := sess.DB(DBNAME).C(REPLYTABLE)

	return replyTable.Update(query, update)
}
func insertReply(docs ...interface{}) error {
	sess := globalSess.Clone()
	defer sess.Close()
	replyTable := sess.DB(DBNAME).C(REPLYTABLE)

	return replyTable.Insert(docs...)
}
func findReply(query, selector interface{}) (Reply, error) {
	sess := globalSess.Copy()
	defer sess.Close()
	replyTable := sess.DB(DBNAME).C(REPLYTABLE)

	reply := Reply{}
	err := replyTable.Find(query).Select(selector).One(&reply)
	return reply, err
}
func findReplyNum(query interface{}) (int, error) {
	sess := globalSess.Copy()
	defer sess.Close()
	replyTable := sess.DB(DBNAME).C(REPLYTABLE)

	return replyTable.Find(query).Count()
}
func findReplys(query, selector interface{}, page, perPage int, fields ...string) ([]Reply, error) {
	sess := globalSess.Copy()
	defer sess.Close()
	replyTable := sess.DB(DBNAME).C(REPLYTABLE)

	replys := []Reply{}
	err := replyTable.Find(query).Select(selector).Sort(fields...).Skip((page - 1) * perPage).Limit(perPage).All(&replys)
	return replys, err
}
func findReplysALL(query interface{}) ([]Reply, error) {
	sess := globalSess.Copy()
	defer sess.Close()
	replyTable := sess.DB(DBNAME).C(REPLYTABLE)

	replys := []Reply{}
	err := replyTable.Find(query).All(&replys)
	return replys, err
}
